<?php
//This Code is published under the conditions of the CDDL (Sun Microsystems) (c) 2008 by Fabian Tschirschnitz
//Diese Klasse liefert rudimentäre Funktionen und Variablen für den  Umgang mit Sequenzen
	abstract class SEQUENCE{
	//ursprünglich übergebene Sequenz (Sicherheitskopie)
		private $seq_arg;
	//Buffer-Sequenz (Hilfsvariable)
		private $seq_buffer;
	//Hauptzustandssequenz
		private $seq_init;
	//Variable mit der in der getseq()-Funktion gearbeitet wird
		private $seq_string;

	//Länge der Sequenz
		private $seq_length;
	//ID der Sequenz im Fasta-Format
		private $seq_id = "> ";

	//Basen
		protected $alphabet = "";

	//Konstruktor der Klasse Sequenz
		function __construct($seq, $id=""){
			$this->seq_init = strtoupper($seq);
			//ID abspeichern
			$this->seq_id .= $id;
			//Sicherheitskopie der Ursprungssequenz anlegen
			$this->seq_arg = $this->seq_init;}

	//Funktion zum extrahieren der derzeitigen Sequenz
		function getseq($na = "?",$arg=false, $keep=false){
			//Kleinschreibung/Whitespaces belassen?
			//nein
			if($keep==false){
			//Argumentssequenz oder aktuellen Zustand der Sequenz auslesen?
			   if(isset($arg) && $arg==true){
			       $this->seq_string = strtoupper($this->seq_arg);}
			   else{
			       $this->seq_string = strtoupper($this->seq_init);}
		       //Whitespaces entfernen
			   $this->seq_string = str_replace(array("\n", "\r", "\t", " ", "\o", "\xOB"), '', $this->seq_string);
			   $this->seq_string = rtrim($this->seq_string);
	           //Nicht-Basen (Zeichen/Zahlen) entfernen
			   $this->seq_string=preg_replace("/\W|[^{$this->alphabet}]|\d/","{$na}",$this->seq_string);}
			//ja, alles belassen
			else{
				//Argumentssequenz oder aktuellen Zustand der Sequenz auslesen?
			    if(isset($arg) && $arg==true){
			       $this->seq_string = $this->seq_arg;}
			    else{
			       $this->seq_string = $this->seq_init;}
			}

			return $this->seq_string;}
	//Sequenz umdrehen
		function reverse(){
			$this->seq_init = strrev($this->seq_init);}

	//komplementäre Sequenz
		function complement(){
			$this->seq_init = strtoupper($this->seq_init);
		   $this->seq_init=strtr($this->seq_init, "ATGCU", "tacga");}
   //Sequenz am Beginn kürzen für Leseraster/Offsets --> ergibt Sequenz%3==0
      function chop($offset){
      	$this->seq_init = preg_replace("/\W|\d/","{$na}",$this->seq_init);
      	$this->seq_init = (substr ($this->seq_init, $offset, floor((strlen($this->seq_init)-$offset)/3)*3));}
	//Länge der Seqeunz ermitteln
		function getseq_length(){
			$this->seq_length = strlen($this->getseq("",true));
			return $this->seq_length;}
	//ID setzen
		function setseq_id($id){
			$this->seq_id .= $id;}
	//ID auslesen
		function getseq_id(){
			//Ausgabe ohne FASTA-Startsymbol
			return strtr($this->seq_id, ">", "");}
	//Suchmuster (z.B. Restriktionsenzyme) markieren
		function mark_pattern($pattern){
			$search_pattern = "/".strtoupper($pattern)."/";
			$this->seq_string = $this->getseq();
			preg_match_all($search_pattern, $this->seq_string, $matches);
			$this->seq_buffer = $this->seq_string;
			foreach($matches as $match){
				foreach($match as $matched){
					$this->seq_buffer = str_replace($matched, strtolower($matched), $this->seq_buffer);
					}
			}
			$this->seq_init = $this->seq_buffer;
		}
	//Anzahl der Vorkommnisse in Sequenz angeben
		function found_pattern($pattern){
		$search_pattern = "/".strtoupper($pattern)."/";
		$result = preg_match_all($search_pattern, $this->getseq(), $matches);
		return $result;}
	}

//DNA-spezifische Eigenschaften/Funktionen
	class DNASEQUENCE extends SEQUENCE{
	//DNA-Basen
		protected $alphabet = "ATGC";

	//Array mit existierenden Aminosäuren/Stopsequenzen (*)
		protected $aminoacids=array("A","C","D","E","F","G","H","I","K","L","M","N","P","Q","R","S","T","V","W","Y","_","?");
	//codierende Basentriplets in Reihenfolge des oben angelegten AS-Arrays mit Hilfe von regex
      protected $triplets=array("(GC. )","(TGT |TGC )","(GAT |GAC )","(GAA |GAG )","(TTT |TTC )","(GG. )","(CAT |CAC )",
      									"(ATT |ATC |ATA )","(AAA |AAG )","(TTA |TTG |CT. )","(ATG )","(AAT |AAC )","(CC. )",
      									"(CAA |CAG )","(CG. |AGA |AGG )","(TC. |AGT |AGC )","(AC. )","(GT. )","(TGG )","(TAT |TAC )",
      									"(TAA |TAG |TGA )","(\S\S\S )");

   	//Sequenzstring in Codons aufgeteilt
	protected $codon_string;
   //Statistikarray
   	protected $stats;
   //Peptid
   	protected $peptide;

   	//Triplets extrahieren aus Sequenz
		function getcodon_string(){
			$this->codon_string = chunk_split($this->getseq(), 3, " ");
			return $this->codon_string;}

	//DNA-Transkribt (mRNA) erhalten
		function getseq_trancribtion(){
			$this->seq_string = $this->getseq();
		   $this->seq_string=strtr($this->seq_string, "ATGC", "uacg");
			return $this->seq_string;}

	//Translation in AS-Sequenz mittels Substitution des Triplet-Arrays durch AS-Array
		function getseq_translation($raster, $seqoffset=0){
		  $offset = $raster + $seqoffset;
		  $this->chop($offset);
        $peptide = preg_replace ($this->triplets, $this->aminoacids, $this->getcodon_string());
        return $peptide;

		}

	//Statistikfunktion
    function getseq_stats(){    //Länge nutzt bereits vorhandene Funktion
		$length = $this->getseq_length();
    //Ergebnisarray-Elemente
		$a=0;$t=0;$g=0;$c=0;$na=0;
		$pa=0;$pt=0;$pg=0;$pc=0;$pna=0;$pg_c=0;
	 //Ergebnisarray
		$stats=array();
		//Anteile von Basen auszählen
			foreach(str_split($this->getseq(),1) as $bases){
				switch($bases){
					case A: $a++; break;
					case T: $t++; break;
					case G: $g++; break;
					case C: $c++; break;
					default: $na++;
				}
			}

		//Prozentswete ermitteln
	     if($length > 0){
	        $pa = $a*100/$length;
	        $pt = $t*100/$length;
	        $pg = $g*100/$length;
	        $pc = $c*100/$length;
	        $pna = $na*100/$length;
	     }
	   //Array füllen
	     $stats = array("length" => $length, "a" => $a, "t" => $t, "g" => $g, "c" => $c, "na" => $na,
	     					  "pa" => $pa, "pt" => $pt, "pg" => $pg, "pc" => $pc, "pna" => $pna, "pg_c" => $pg+$pc);

	     return $stats;
    }

	}

	class RNASEQUENCE extends SEQUENCE{
	//RNA-Basen
		protected $alphabet = "AUGC";

	}

	class ASSEQUENCE extends SEQUENCE{
	//Aminosäuren
		protected $alphabet = "ACDEFGHIKLMNPQRSTVWY_";

		function complement(){echo "Funktion nicht auf Aminosäure-Sequenzen anwendbar.";}

	}
?>
